package common;

import com.sun.xml.internal.fastinfoset.tools.FI_SAX_Or_XML_SAX_DOM_SAX_SAXEvent;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ListIterator;

/*
* 1. 在notify过程中增加的observer，需要等到下次notify才生效
* 2. 在notify过程中删除的observer，当次如果还没有notify，那么不要notify
* 3.
* */

public class NotificationCenter
{
    public interface Observer
    {
        void onNotify(Object sender, String eventName, Object eventParams);
    }

    private static NotificationCenter _instance = new NotificationCenter();

    public static NotificationCenter getInstance() {
        return _instance;
    }

    public void addObserver(String event, Observer observer, Object sender)
    {
        if (event == null || event.length() == 0 || observer == null) {
            return;
        }

        synchronized (_observers) {
            LinkedList<ObserverHolder> list =  _observers.get(event);
            if (list == null) {
                list = new LinkedList<>();
                _observers.put(event, list);
            }
            ObserverHolder holder = new ObserverHolder();
            holder.observer = new WeakReference<>(observer);
            holder.sender = sender;
            list.add(holder);
        }
    }

    public void removeObserver(String event, Observer observer)
    {
        if (event == null || event.length() == 0 || observer == null) {
            return;
        }

        synchronized (_observers) {
            LinkedList<ObserverHolder> list = _observers.get(event);
            if (list == null) {
                return;
            }

            ListIterator<ObserverHolder> iter = list.listIterator();
            while (iter.hasNext())
            {
                ObserverHolder holder = iter.next();
                Observer obj = holder.observer.get();
                if (obj == null || obj == observer) {
                    iter.remove();
                }
            }
        }
    }


    public void notify(Object sender, String eventName, Object eventParams)
    {
        LinkedList<ObserverHolder> notifyList = new LinkedList<>();

        synchronized (_observers) {
            LinkedList<ObserverHolder> list =  _observers.get(eventName);
            if (list == null) {
                return;
            }
            notifyList.addAll(list);
        }

        ListIterator<ObserverHolder> iter = notifyList.listIterator();
        while (iter.hasNext()) {
            ObserverHolder holder = iter.next();

            Observer observer = holder.observer.get();
            if (observer == null) {
                iter.remove();
                continue;
            }

            if (holder.sender != null && holder.sender != sender) {
                continue;
            }

            synchronized (_observers) {
                LinkedList<ObserverHolder> list =  _observers.get(eventName);
                if (list.contains(holder)) {
                    observer.onNotify(sender, eventName, eventParams);
                }
            }
        }
    }

    private static class ObserverHolder
    {
        Object sender;
        WeakReference<Observer> observer;
    }

    private final HashMap<String, LinkedList<ObserverHolder>> _observers = new HashMap<>();
}
